/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pl.edu.agh.student.logic.dao;

import java.lang.reflect.ParameterizedType;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.core.Events;
import org.jboss.seam.log.Log;
import pl.edu.agh.student.model.AbstractEntity;

/**
 *
 * @author janburkot
 */
public abstract class GenericDaoImpl<T extends AbstractEntity>
        implements GenericDao<T> {

    @In("entityManager")
    protected EntityManager entityManager;
    @Logger
    protected Log log;
    protected final Class<T> clazz;

    @SuppressWarnings("unchecked")
    protected GenericDaoImpl() {
        this.clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    /**
     * {@inheritDoc}
     */
    public final T find(final long id) {

        assert clazz != null : "clazz != null";
        return entityManager.find(clazz, id);
    }

    /**
     * {@inheritDoc}
     */
    private final void save(final T entity) {
        assert entity != null : "entity != null";

        if (entity.getId() == null) {
            entityManager.persist(entity);
        }

        assert entityManager.contains(entity);

        Events.instance().raiseEvent(
                "pl.edu.agh.student.persited." + entity.getClass().getSimpleName());

        entityManager.flush();
        //return "success";

    }

    /**
     * {@inheritDoc}
     */
    public void saveOrUpdate(final T entity) {
        assert entity != null : "entity != null";

        if (!isManaged(entity)) {
            save(entity);
        }
        entityManager.flush();
        //return "success";
    }

    public void delete(final T entity) {
        log.debug("remove entity #0", entity);

        entityManager.remove(entity);

        Events.instance().raiseEvent(
                "pl.edu.agh.student.deleted." + entity.getClass().getSimpleName());
        
        entityManager.flush();
        //return "success";
    }

    public void refresh(T entity) {
        log.debug("refresh entity #0", entity);
        if (isManaged(entity)) {
            entityManager.refresh(entity);
        } else {
            entity = null;
        }
    }

    private boolean isManaged(final T entity) {
        return entity.getId() == null ? false : true;
    }
    
    public List<T> findByProperty(String name, Object value){
        final Query query = entityManager.createQuery("select x from "+clazz.getName()+" x where "+name+" = :"+name)
                .setParameter(name, value);
        return query.getResultList();
    } 
}
